package Singleton;
import java.util.concurrent.locks.ReentrantLock;
/**
 * 单例模式 优化版
 * 双重锁机制
 * Created by RXJ on 2017/12/12.
 * key proint
 * 1.为了防止new Singleton被执行多次，因此在new操作之前加上Synchronized 同步锁，
 * 锁住整个类（注意，这里不能使用对象锁）。
 *
 * 2.进入Synchronized 临界区以后，还要再做一次判空。
 * 因为当两个线程同时访问的时候，线程A构建完对象，
 * 线程B也已经通过了最初的判空验证，不做第二次判空的话，
 * 线程B还是会再次构建instance对象。
 *
 *
 */
public class Singleton2 {
    //私有构造函数
    private Singleton2(){

    }
    //单例对象
    /*
    volatile
    修饰符阻止变量访问前后的指令重排，保证指令的执行顺序
     */
    private volatile  static Singleton2 instance = null ;

    //静态工厂方法
    //获取单列对象方法
    public static Singleton2 getInstance(){
        if(instance == null){   //双重检测机制
           synchronized (Singleton2.class){ //同步锁
               if(instance == null){ //双重检测机制
                   instance = new Singleton2();
               }
           }
        }
        return  instance;
    }

/*
弊端：
比如java中简单的一句 instance = new Singleton，会被编译器编译成如下JVM指令：

memory =allocate();    //1：分配对象的内存空间
ctorInstance(memory);  //2：初始化对象
instance =memory;     //3：设置instance指向刚分配的内存地址

但是这些指令顺序并非一成不变，有可能会经过JVM和CPU的优化，指令重排成下面的顺序：

memory =allocate();    //1：分配对象的内存空间
instance =memory;     //3：设置instance指向刚分配的内存地址
ctorInstance(memory);  //2：初始化对象


 */
}
